package com.gandong8.trace.tool.util;

import com.gandong8.trace.tool.core.SystemClock;
import com.gandong8.trace.tool.domain.ResponseData;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.gandong8.trace.tool.domain.RequestData;
import lombok.Data;
import org.apache.commons.codec.binary.Base64;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.Serializable;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

/**
 * https://ding-doc.dingtalk.com/doc#/serverapi2/qf2nxq
 */
public class DingDingUtil {
    private static String dingUrl = "https://oapi.dingtalk.com/robot/send";

    public static Boolean send(String accessToken, String secret, DingRequest dingRequest) {
        dingRequest.setMsgtype(dingRequest.getDingType().name().toLowerCase());
        dingRequest.setDingType(null);
        return sendMsg(accessToken, secret, JsonUtil.toStr(dingRequest));
    }

    public static Boolean sendMarkdown(String accessToken, String secret, String title, String content) {
        String textMsg = "{\n" +
                "    \"msgtype\": \"markdown\", \n" +
                "    \"markdown\": {\n" +
                "        \"title\": \""+ title +"\",\n" +
                "        \"text\": \""+ content +"\"\n" +
                "    }\n" +
                "}";
        return sendMsg(accessToken, secret, textMsg);
    }

    public static Boolean sendLink(String accessToken, String secret, String text, String title, String picUrl, String messageUrl) {
        String textMsg = "{\n" +
                "    \"msgtype\": \"link\", \n" +
                "    \"link\": {\n" +
                "        \"text\": \""+text+"\", \n" +
                "        \"title\": \""+title+"\", \n" +
                "        \"picUrl\": \""+picUrl+"\", \n" +
                "        \"messageUrl\": \""+messageUrl+"\"\n" +
                "    }\n" +
                "}";
        return sendMsg(accessToken, secret, textMsg);
    }

    public static Boolean sendText(String accessToken, String secret, String content) {
        String textMsg = "{ \"msgtype\": \"text\", \"text\": {\"content\": \"" + content + "\"}}";
        return sendMsg(accessToken, secret, textMsg);
    }

    public static Boolean sendText(String accessToken, String secret, String content, String atMobile) {
        String textMsg = "{\n" +
                "    \"msgtype\": \"text\", \n" +
                "    \"text\": {\n" +
                "        \"content\": \""+ content +"\"\n" +
                "    }, \n" +
                "    \"at\": {\n" +
                "        \"atMobiles\": [\n" +
                "            " + atMobile +
                "        ], \n" +
                "        \"isAtAll\": false\n" +
                "    }\n" +
                "}";
        return sendMsg(accessToken, secret, textMsg);
    }

    private static Boolean sendMsg(String accessToken, String secret, String textMsg) {
        Long timestamp = SystemClock.now();
        String sign = sign(secret, timestamp);
        String url = dingUrl + "?access_token=" + accessToken + "&timestamp=" + timestamp + "&sign=" + sign;
        RequestData requestData = new RequestData(url, 2000,2000).setPostJson(textMsg);
        try {
            ResponseData responseData = HttpUtil.doPost(requestData);
            DingResult dingResult = JsonUtil.toObj(responseData.getData(), DingResult.class);
            if(dingResult.getErrcode().equals(0)) {
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    private static String sign(String secret, Long timestamp){
        try {
            String str = timestamp + "\n" + secret;
            Mac mac = Mac.getInstance("HmacSHA256");
            mac.init(new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
            byte[] signData = mac.doFinal(str.getBytes(StandardCharsets.UTF_8));
            return URLEncoder.encode(new String(Base64.encodeBase64(signData)),StandardCharsets.UTF_8.name());
        } catch (Exception e) {
            return null;
        }
    }
    @JsonInclude(JsonInclude.Include.NON_NULL)
    @Data
    public static class DingRequest implements Serializable {
        //text,markdown, link
        private String msgtype;
        private DingType dingType;
        private DingLink link;
        private DingText text;
        private DingMarkdown markdown;
        private DingAt at;
    }
    public static enum DingType {
        TEXT("text"),
        LINK("link"),
        MARKDOWN("markdown");

        DingType(String type) {
        }
    }
    @Data
    public static class DingLink implements Serializable {
        private String text;
        private String title;
        private String picUrl;
        private String messageUrl;
    }
    @Data
    public static class DingText implements Serializable {
        private String content;
    }

    @Data
    public static class DingMarkdown implements Serializable {
        private String text;
        private String title;
    }

    @Data
    public static class DingAt implements Serializable {
        private List<String> atMobiles = new ArrayList<>();
        private Boolean isAtAll = false;
    }

    @Data
    public static class DingResult implements Serializable {
        private Integer errcode;
        private String errmsg;
    }

    public static void main(String[] args) {
        String token = "";
        String secret = "";

        DingRequest dingRequest = new DingRequest();
        dingRequest.setDingType(DingType.MARKDOWN);
        DingMarkdown markdown = new DingMarkdown();
        markdown.setText("aa");
        markdown.setTitle("bb");
        dingRequest.setMarkdown(markdown);
        send(token, secret, dingRequest);

        //DingRequest dingRequest = new DingRequest();
        dingRequest.setDingType(DingType.TEXT);
        DingText dingText = new DingText();
        dingText.setContent("test");
        dingRequest.setText(dingText);
        send(token, secret, dingRequest);

    }

}
